<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Chapter 3. Transaction Management</title>
    <link rel="stylesheet" href="gettingStarted.css" type="text/css" />
    <meta name="generator" content="DocBook XSL Stylesheets V1.73.2" />
    <link rel="start" href="index.html" title="Getting Started with Berkeley DB, Java Edition High Availability Applications" />
    <link rel="up" href="index.html" title="Getting Started with Berkeley DB, Java Edition High Availability Applications" />
    <link rel="prev" href="two-node.html" title="Configuring Two-Node Groups" />
    <link rel="next" href="consistency.html" title="Managing Consistency" />
  </head>
  <body>
    <div class="navheader">
      <table width="100%" summary="Navigation header">
        <tr>
          <th colspan="3" align="center">Chapter 3. Transaction Management</th>
        </tr>
        <tr>
          <td width="20%" align="left"><a accesskey="p" href="two-node.html">Prev</a> </td>
          <th width="60%" align="center"> </th>
          <td width="20%" align="right"> <a accesskey="n" href="consistency.html">Next</a></td>
        </tr>
      </table>
      <hr />
    </div>
    <div class="chapter" lang="en" xml:lang="en">
      <div class="titlepage">
        <div>
          <div>
            <h2 class="title"><a id="txn-management"></a>Chapter 3. Transaction Management</h2>
          </div>
        </div>
      </div>
      <div class="toc">
        <p>
          <b>Table of Contents</b>
        </p>
        <dl>
          <dt>
            <span class="sect1">
              <a href="txn-management.html#durability">Managing Durability</a>
            </span>
          </dt>
          <dd>
            <dl>
              <dt>
                <span class="sect2">
                  <a href="txn-management.html#durabilitycontrols">Durability Controls</a>
                </span>
              </dt>
              <dt>
                <span class="sect2">
                  <a href="txn-management.html#commitsync">Commit File Synchronization</a>
                </span>
              </dt>
              <dt>
                <span class="sect2">
                  <a href="txn-management.html#managingacks">Managing Acknowledgements</a>
                </span>
              </dt>
            </dl>
          </dd>
          <dt>
            <span class="sect1">
              <a href="consistency.html">Managing Consistency</a>
            </span>
          </dt>
          <dd>
            <dl>
              <dt>
                <span class="sect2">
                  <a href="consistency.html#setconsistencypolicy">Setting Consistency Policies</a>
                </span>
              </dt>
              <dt>
                <span class="sect2">
                  <a href="consistency.html#timeconsistency">Time Consistency Policies</a>
                </span>
              </dt>
              <dt>
                <span class="sect2">
                  <a href="consistency.html#commitpointconsistency">Commit Point Consistency Policies</a>
                </span>
              </dt>
            </dl>
          </dd>
          <dt>
            <span class="sect1">
              <a href="availability.html">Availability</a>
            </span>
          </dt>
          <dd>
            <dl>
              <dt>
                <span class="sect2">
                  <a href="availability.html#writeavailability">Write Availability</a>
                </span>
              </dt>
              <dt>
                <span class="sect2">
                  <a href="availability.html#readavailability">Read Availability</a>
                </span>
              </dt>
            </dl>
          </dd>
          <dt>
            <span class="sect1">
              <a href="cons_and_dur.html">Consistency and Durability Use Cases</a>
            </span>
          </dt>
          <dd>
            <dl>
              <dt>
                <span class="sect2">
                  <a href="cons_and_dur.html#outonthetown">Out on the Town</a>
                </span>
              </dt>
              <dt>
                <span class="sect2">
                  <a href="cons_and_dur.html#biolabs">Bio Labs, Inc</a>
                </span>
              </dt>
            </dl>
          </dd>
          <dt>
            <span class="sect1">
              <a href="txnrollback.html">Managing Transaction Rollbacks</a>
            </span>
          </dt>
          <dt>
            <span class="sect1">
              <a href="runtransaction.html">Example Run Transaction Class</a>
            </span>
          </dt>
          <dd>
            <dl>
              <dt>
                <span class="sect2">
                  <a href="runtransaction.html#exruntransaction">RunTransaction Class</a>
                </span>
              </dt>
              <dt>
                <span class="sect2">
                  <a href="runtransaction.html#usingruntransaction">Using RunTransaction</a>
                </span>
              </dt>
            </dl>
          </dd>
        </dl>
      </div>
      <p>
        A JE HA application is essentially a transactional application
        that distributes its data across multiple environments for you. The
        assumption is that these environments are on separate physical
        hosts, so the distribution of your data is performed over TCP/IP
        connections.
    </p>
      <p>
        Because of this distribution activity, several new dimensions are
        added to your transactional management. In particular, there is
        more to consider in the areas of durability, consistency and
        performance than you have to think about for single-environment
        applications.
    </p>
      <p>
        Before continuing, some definitions are in order:
    </p>
      <div class="orderedlist">
        <ol type="1">
          <li>
            <p>
                <span class="emphasis"><em>Durability</em></span> is defined by how likely
                your data will continue to exist in the presence of 
                hardware breakage or a software crash. The first goal of
                any durability scheme is to get your data stored onto
                physical media. After that, to make your data even more
                durable, you will usually start to consider your backup
                schemes. 
            </p>
            <p>
                By its very nature, a JE HA application is offering you
                more data durability than does a traditional transactional
                application. This is because your HA application is
                distributing your data across multiple environments (which
                we assume are on multiple physical machines), which means
                that data backups are built into the application. The more
                backups, the more durable your application is.
            </p>
          </li>
          <li>
            <p>
                <span class="emphasis"><em>Consistency</em></span> is defined by how
                <span class="emphasis"><em>current</em></span> your data is. In a traditional
                transactional application, consistency is guaranteed by
                allowing you to group multiple read and write operations in
                a single atomic unit, which is defined by the transactional
                handle. This level of consistency continues to exist for
                your HA application, but in addition you must concern
                yourself with how consistent (or correct) the data is
                across the various nodes in the replication group.
            </p>
            <p>
                Because the replication group is a collection of differing
                machines connected by a network, some amount of a delay in
                data updates is to be naturally expected across the
                Replicas. The amount of delay that you will see is
                determined by the number and size of the data updates, the
                performance of your network, the performance of the
                hardware on which your nodes are running, and whether your
                nodes are persistently available on the network (as opposed
                to being down or offline or otherwise not on the network
                for some period of time).
            </p>
            <p>
                A highly consistent HA application, then, is an application
                where the data across all nodes in the replication group is
                identical or very nearly identical all the time. A not very
                consistent HA application is one where data across the
                replication group is frequently stale or out of date
                relative to the data contained on the Master node.
            </p>
          </li>
          <li>
            <p>
                <span class="emphasis"><em>Performance</em></span> is simply how fast your HA
                application is at performing read and write requests. By
                its very nature, an HA application tends to perform much
                better than a traditional transactional application at
                read-only requests. This is because you have multiple
                machines that are available to service read-only requests.
                The only tricky thing here is to make sure you load balance
                your read requests appropriately across all your nodes so
                that you do not have some nodes that are swamped with
                requests while others are mostly idle.
            </p>
            <p>
                Write performance for an HA application is a mixed bag.
                Depending on your goals, you can make the HA application
                perform better than a traditional transactional
                application that is committing writes to the disk
                synchronously. However, in doing so 
                you will compromise your data's durability and consistency
                guarantees. This is no different than configuring a
                traditional transactional application to commit
                transactions asynchronously to disk, and so lose the
                guarantee that the write is stored on physical media before
                the transaction completes. However, the good news is that
                because of the distributed nature of the HA application,
                you have a better durability guarantee than the
                asynchronously committing single-environment transactional
                application. That is, by "committing to the network" you
                have a fairly good chance of a write making it to disk
                somewhere on some node.
            </p>
            <p>
                Mostly, though, HA applications commit a transaction and
                then wait for an acknowledgement from some number of nodes
                before the transaction is complete.  An HA application
                running with quorum acknowledgements and write no sync
                durability can exhibit equal or better write performance
                than a single node standalone application, but your write
                performance will ultimately depend on your application's
                configuration.
            </p>
          </li>
        </ol>
      </div>
      <p>
        As you design your HA application, remember that each of these 
        characteristics are interdependent. You cannot, for example,
        configure your application to have extremely high durability
        without sacrificing some amount of performance. A highly
        consistent application may have to make sacrifices in durability. A
        high performance HA application may require you to make trade-offs
        in both durability and consistency.
    </p>
      <div class="sect1" lang="en" xml:lang="en">
        <div class="titlepage">
          <div>
            <div>
              <h2 class="title" style="clear: both"><a id="durability"></a>Managing Durability</h2>
            </div>
          </div>
        </div>
        <div class="toc">
          <dl>
            <dt>
              <span class="sect2">
                <a href="txn-management.html#durabilitycontrols">Durability Controls</a>
              </span>
            </dt>
            <dt>
              <span class="sect2">
                <a href="txn-management.html#commitsync">Commit File Synchronization</a>
              </span>
            </dt>
            <dt>
              <span class="sect2">
                <a href="txn-management.html#managingacks">Managing Acknowledgements</a>
              </span>
            </dt>
          </dl>
        </div>
        <p>
            A highly durable application is one where you attempt to make
            sure you do not lose data, ever. This is frequently (but not
            always) one of the most pressing design considerations for any
            application that manages data. After all, data often equals
            money because the data you are managing could involve billing
            or inventory information. But even if your application is not
            managing information that directly relates to money, a loss of
            data may very well cost your enterprise money in terms of the
            time and resources necessary to reacquire the information.
        </p>
        <p>
            HA applications attempt to increase their data
            durability guarantees by distributing data writes across
            multiple physical machines on the network. By spreading the
            data in this way, you are placing it on stable storage on
            multiple physical hard drives, CPUs and power supplies.
            Obviously, the more physical resources available to contain
            your data, the more durable it is.
        </p>
        <p>
            However, as you increase your data durability, you will
            probably lower your consistency guarantees and probably your
            write performance. Read performance may also take a hit,
            depending on how many physical machines you include in the mix
            and how high a durability guarantee you want. In order to
            understand why, you have to understand how JE HA
            applications handle transactional commits.
        </p>
        <div class="sect2" lang="en" xml:lang="en">
          <div class="titlepage">
            <div>
              <div>
                <h3 class="title"><a id="durabilitycontrols"></a>Durability Controls</h3>
              </div>
            </div>
          </div>
          <p>
                By default, JE HA makes transactional commit operations
                on the Master wait to return from the operation until they receive
                acknowledgements from some number of Replicas. Each
                Replica, in turn, will only return an acknowledgement once
                the write operation has met whatever durability requirement
                exists for the Replica. (For example, you can require the
                Replicas to successfully flush the write operation to disk
                before returning an acknowledgement to the Master.)
            </p>
          <div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
            <h3 class="title">Note</h3>
            <p>
                    Be aware that write operations received on the Replica
                    from the Master have lock priority. This means that if
                    the Replica is currently servicing a read request, it
                    might have to retry the read operation should a write
                    from the Master preempt the read lock. For this reason,
                    you can see read performance degradation if you have
                    Replicas that are heavily loaded with read requests at
                    a time when the Master is performing a lot of write
                    activity. The solution to this is to add
                    additional nodes to your replication group and/or better
                    load-balance your read requests across the Replicas.
                </p>
          </div>
          <p>
                There are three things to control when you design your
                durability guarantee:
            </p>
          <div class="itemizedlist">
            <ul type="disc">
              <li>
                <p>
                        Whether the Master synchronously writes the
                        transaction to disk. This is no different from the
                        durability consideration that you have for a
                        stand-alone transactional application.
                    </p>
              </li>
              <li>
                <p>
                        Whether the Replica synchronously writes the
                        transaction to disk before returning an
                        acknowledgement to the Master, if any.
                    </p>
              </li>
              <li>
                <p>
                        How many, if any, Replicas must acknowledge the
                        transaction commit before the commit operation on
                        the Master can complete.
                    </p>
              </li>
            </ul>
          </div>
          <p>
                You can configure your durability policy on a
                transaction-by-transaction basis using 
                <a class="ulink" href="../java/com/sleepycat/je/TransactionConfig.html#setDurability(com.sleepycat.je.Durability)" target="_top">TransactionConfig.setDurability()</a>, or on an
                environment-wide basis using
                <a class="ulink" href="../java/com/sleepycat/je/EnvironmentMutableConfig.html#setDurability(com.sleepycat.je.Durability)" target="_top">EnvironmentMutableConfig.setDurability()</a>.
            </p>
        </div>
        <div class="sect2" lang="en" xml:lang="en">
          <div class="titlepage">
            <div>
              <div>
                <h3 class="title"><a id="commitsync"></a>Commit File Synchronization</h3>
              </div>
            </div>
          </div>
          <p>
                Synchronization policies are described in the
                <em class="citetitle">Berkeley DB, Java Edition Getting Started with Transaction Processing</em> guide. However, for the
                sake of completeness, we briefly cover this topic here
                again.
            </p>
          <p>
                You define your commit synchronization policy by using 
                a <a class="ulink" href="../java/com/sleepycat/je/Durability.html" target="_top">Durability</a> class object. For HA applications, the
                <a class="ulink" href="../java/com/sleepycat/je/Durability.html" target="_top">Durability</a> class constructor must define the
                synchronization policy for both the Master and the Master's
                replicas. The synchronization policy does not have to be
                the same for both Master and Replica.
            </p>
          <p>
                You can use the following constants to define a
                synchronization policy:
            </p>
          <div class="itemizedlist">
            <ul type="disc">
              <li>
                <p>
                        <a class="ulink" href="../java/com/sleepycat/je/Durability.SyncPolicy.html#SYNC" target="_top">Durability.SyncPolicy.SYNC</a>
                    </p>
                <p>
                        Write and synchronously flush the log to disk upon
                        transaction commit. This offers the most durable
                        transaction configuration because the commit
                        operation will not return until all of the disk I/O
                        is complete. But, conversely, this offers the worse
                        possible write performance because disk I/O is an
                        expensive and time-consuming operation.
                    </p>
              </li>
              <li>
                <p>
                        <a class="ulink" href="../java/com/sleepycat/je/Durability.SyncPolicy.html#NO_SYNC" target="_top">Durability.SyncPolicy.NO_SYNC</a>
                    </p>
                <p>
                        Do not synchronously flush the log on transaction
                        commit. All of the transaction's write activity is
                        held entirely in memory when the transaction
                        completes. The log will eventually make it to disk
                        (barring an application hardware crash of some kind).
                        However, the application's thread of control is
                        free to continue operations without waiting for
                        expensive disk I/O to complete.
                    </p>
                <p>
                        This represents the least durable configuration
                        that you can provide for your transactions. But it
                        also offers much better write performance than the
                        other options.
                    </p>
              </li>
              <li>
                <p>
                        <a class="ulink" href="../java/com/sleepycat/je/Durability.SyncPolicy.html#WRITE_NO_SYNC" target="_top">Durability.SyncPolicy.WRITE_NO_SYNC</a>
                    </p>
                <p>
                        Log data is synchronously written to the OS's file
                        system buffers upon transaction commit, but the
                        data is not actually forced to disk. This protects
                        your write activities from an application crash,
                        but not from a hardware failure.
                    </p>
              </li>
              <li>
                <p>
                        This policy represents an intermediate durability
                        guarantee. It is not has strong as SYNC, but is
                        also not as weak as NO_SYNC. Conversely, it
                        performs better than NO_SYNC (because your
                        application does not have to wait for actual disk
                        I/O), but it does not perform quite as well as SYNC
                        (because data still must be written to the file
                        system buffers).
                    </p>
              </li>
            </ul>
          </div>
        </div>
        <div class="sect2" lang="en" xml:lang="en">
          <div class="titlepage">
            <div>
              <div>
                <h3 class="title"><a id="managingacks"></a>Managing Acknowledgements</h3>
              </div>
            </div>
          </div>
          <p>
                Whenever a Master commits a transaction, by default it
                waits for acknowledgements from a majority of its Replicas
                before the commit operation on the Master completes.
                By default, Replicas respond with an acknowledgement once they have
                successfully written the transaction to their local disk.
            </p>
          <p>
                Acknowledgements are expensive operations. They involve both
                network traffic, as well as disk I/O at multiple physical
                machines. So on the one hand, acknowledgements help to
                increase your durability guarantees. On the other, they
                hurt your application's performance, and may have a
                negative impact on your application's consistency
                guarantee.
            </p>
          <p>
                For this reason, JE allows you to manage
                acknowledgements for your HA application. As is the case
                with synchronization policies, you do this using the
                <a class="ulink" href="../java/com/sleepycat/je/Durability.html" target="_top">Durability</a> class. As a part of this class' constructor,
                you can provide it with one of the following constants:
            </p>
          <div class="itemizedlist">
            <ul type="disc">
              <li>
                <p>
                        <a class="ulink" href="../java/com/sleepycat/je/Durability.ReplicaAckPolicy.html#ALL" target="_top">Durability.ReplicaAckPolicy.ALL</a>
                    </p>
                <p>
                        All of the Replicas must acknowledge the
                        transactional commit. This represents the highest
                        possible durability guarantee for your HA application,
                        but it also represents the poorest performance. For
                        best results, do not use this policy unless your
                        replication group contains a very small number of
                        replicas, and those replicas are all on
                        extremely reliable networks and servers.
                    </p>
              </li>
              <li>
                <p>
                        <a class="ulink" href="../java/com/sleepycat/je/Durability.ReplicaAckPolicy.html#NONE" target="_top">Durability.ReplicaAckPolicy.NONE</a>
                    </p>
                <p>
                        The Master will not wait for any acknowledgements
                        from its Replicas. In this case, your durability
                        guarantee is determined entirely by the
                        synchronization policy your Master is using for its
                        transactional commits. This policy also represents
                        the best possible choice for write
                        performance.
                    </p>
              </li>
              <li>
                <p>
                        <a class="ulink" href="../java/com/sleepycat/je/Durability.ReplicaAckPolicy.html#SIMPLE_MAJORITY" target="_top">Durability.ReplicaAckPolicy.SIMPLE_MAJORITY</a>
                    </p>
                <p>
                        A simple majority of the Replicas must return
                        and acknowledgement before the commit operation 
                        returns on the Master.  This is the default policy.
                        It should work well for most applications unless
                        you need an extremely high durability
                        guarantee, have a very large number of Replicas, or
                        you otherwise have performance concerns that cause
                        you to want to avoid acknowledgements altogether.
                    </p>
              </li>
            </ul>
          </div>
          <p>
                You can configure your synchronization policy on a
                transaction-by-transaction basis using 
                <a class="ulink" href="../java/com/sleepycat/je/TransactionConfig.html#setDurability(com.sleepycat.je.Durability)" target="_top">TransactionConfig.setDurability()</a>, or on an
                environment-wide basis using
                <a class="ulink" href="../java/com/sleepycat/je/EnvironmentMutableConfig.html#setDurability(com.sleepycat.je.Durability)" target="_top">EnvironmentMutableConfig.setDurability()</a>.
                For example:
            </p>
          <pre class="programlisting">   EnvironmentConfig envConfig = new EnvironmentConfig();
   envConfig.setAllowCreate(true);
   envConfig.setTransactional(true);

   <strong class="userinput"><code>// Require no synchronization for transactional commit on the 
   // Master, but full synchronization on the Replicas. Also,
   // wait for acknowledgements from a simple majority of Replicas.
   Durability durability =
          new Durability(Durability.SyncPolicy.WRITE_NO_SYNC,
                         Durability.SyncPolicy.NO_SYNC,
                         Durability.ReplicaAckPolicy.SIMPLE_MAJORITY);

   envConfig.setDurability(durability);</code></strong>

   // Identify the node
   ReplicationConfig repConfig = 
        new ReplicationConfig("PlanetaryRepGroup",
                              "Jupiter",
                              "jupiter.acme.com:5002");

   // Use the node at mercury.acme.com:5001 as a helper to find
   // the rest of the group.
   repConfig.setHelperHosts("mercury.acme.com:5001");

   ReplicatedEnvironment repEnv =
      new ReplicatedEnvironment(home, repConfig, envConfig); </pre>
          <p>
                Note that at the time of a transaction commit, if the
                Master is not in contact with enough Replicas to meet the
                transaction's durability policy, the transaction commit
                operation will throw an <a class="ulink" href="../java/com/sleepycat/je/rep/InsufficientReplicasException.html" target="_top">InsufficientReplicasException</a>.
                The proper action to take upon encountering this exception
                is to abort the transaction, wait a small period of time in
                the hopes that more Replicas will become available, then
                retry the exception. See
                <a class="xref" href="runtransaction.html" title="Example Run Transaction Class">Example Run Transaction Class</a>
                for example code that implements this retry loop.
            </p>
          <p>
                You can also see an <a class="ulink" href="../java/com/sleepycat/je/rep/InsufficientReplicasException.html" target="_top">InsufficientReplicasException</a> when
                you begin a transaction if the Master fails to be in
                contact with enough Replicas to meet the acknowledgement
                policy. To manage this, you can configure how long the
                transaction begin operation will wait for enough Replicas
                before throwing this exception. You use the
                <a class="ulink" href="../java/com/sleepycat/je/rep/ReplicationConfig.html#INSUFFICIENT_REPLICAS_TIMEOUT" target="_top">INSUFFICIENT_REPLICAS_TIMEOUT</a> configuration option, which 
                you can set using the <a class="ulink" href="../java/com/sleepycat/je/rep/ReplicationConfig.html#setConfigParameter(java.lang.String,java.lang.String)" target="_top">ReplicationConfig.setConfigParameter()</a>
                method.
            </p>
          <div class="sect3" lang="en" xml:lang="en">
            <div class="titlepage">
              <div>
                <div>
                  <h4 class="title"><a id="replicacommittimeout"></a>Managing Acknowledgement Timeouts</h4>
                </div>
              </div>
            </div>
            <p>
                    In addition to the acknowledgement policies, you have
                    to also consider your replication acknowledgement
                    timeout value. This value specifies the maximum amount
                    of time that the Master will wait for acknowledgements
                    from its Replicas. 
                </p>
            <p>
                    If the
                    Master commits a transaction and the timeout value is
                    exceeded while waiting for enough acknowledgements, the
                    <a class="ulink" href="../java/com/sleepycat/je/Transaction.html#commit()" target="_top">Transaction.commit()</a> method will throw an
                    <a class="ulink" href="../java/com/sleepycat/je/rep/InsufficientAcksException.html" target="_top">InsufficientAcksException</a> exception. In this event,
                    the transaction has been committed on the Master, so at
                    least locally the transaction's durability policy has
                    been met. However, the transaction might not have been
                    committed on enough Replicas to guarantee your HA
                    application's overall durability policy. 
                </p>
            <p>
                    There can be a lot of reasons why the Master did not
                    get enough acknowledgements before the timeout value,
                    such as a slow network. As a result, whether you
                    consider the transaction to be a failure is up to you.
                    However, given enough time, all of your Replicas should
                    eventually catch up to the Master.
                </p>
            <p>
                    The default value for this timeout is 5 seconds, which
                    should work for most cases where an acknowledgement
                    policy is in use. However, if you have a very large
                    number of Replicas, or if you have a very unreliable
                    network, then you might see a lot of
                    <a class="ulink" href="../java/com/sleepycat/je/rep/InsufficientAcksException.html" target="_top">InsufficientAcksException</a> exceptions. In this case,
                    you should either increase this timeout value, relax
                    your acknowledgement policy, or find out why your
                    hardware and/or network is performing so poorly.
                </p>
            <p>
                    You can configure your acknowledgement policy using the
                    <a class="ulink" href="../java/com/sleepycat/je/rep/ReplicationConfig.html#setReplicaCommitTimeout(long,java.util.concurrent.TimeUnit)" target="_top">ReplicationConfig.setReplicaCommitTimeout()</a> method.
                </p>
            <pre class="programlisting">   EnvironmentConfig envConfig = new EnvironmentConfig();
   envConfig.setAllowCreate(true);
   envConfig.setTransactional(true);

   // Require no synchronization for transactional commit on the 
   // Master, but full synchronization on the Replicas. Also,
   // wait for acknowledgements from a simple majority of Replicas.
   Durability durability =
          new Durability(Durability.SyncPolicy.WRITE_NO_SYNC,
                         Durability.SyncPolicy.NO_SYNC,
                         Durability.ReplicaAckPolicy.SIMPLE_MAJORITY);

   envConfig.setDurability(durability);

   // Identify the node
   ReplicationConfig repConfig = 
        new ReplicationConfig("PlanetaryRepGroup",
                              "Jupiter",
                              "jupiter.acme.com:5002");
 
   // Use the node at mercury.acme.com:5001 as a helper to find the rest
   // of the group.
   repConfig.setHelperHosts("mercury.acme.com:5001");

   <strong class="userinput"><code>// Set a acknowledgement timeout that is slightly longer
   // than the default 5 seconds.
   repConfig.setReplicaCommitTimeout(7, TimeUnit.SECONDS);</code></strong>

   ReplicatedEnvironment repEnv =
      new ReplicatedEnvironment(home, repConfig, envConfig); </pre>
          </div>
        </div>
      </div>
    </div>
    <div class="navfooter">
      <hr />
      <table width="100%" summary="Navigation footer">
        <tr>
          <td width="40%" align="left"><a accesskey="p" href="two-node.html">Prev</a> </td>
          <td width="20%" align="center"> </td>
          <td width="40%" align="right"> <a accesskey="n" href="consistency.html">Next</a></td>
        </tr>
        <tr>
          <td width="40%" align="left" valign="top">Configuring Two-Node Groups </td>
          <td width="20%" align="center">
            <a accesskey="h" href="index.html">Home</a>
          </td>
          <td width="40%" align="right" valign="top"> Managing Consistency</td>
        </tr>
      </table>
    </div>
  </body>
</html>
